"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RoomState = exports.Room = void 0;
const Config_1 = require("../Config");
const MySQLService_1 = __importDefault(require("../service/MySQLService"));
const Mgr_1 = __importDefault(require("../hall/Mgr"));
class Room {
    //TODO 三名玩家都退出游戏时，关闭房间
    constructor(id, cipher = null) {
        this.id = -1;
        this.cipher = null; //房间暗号 四个数字，string类型
        this.players = new Array(); //玩家
        this.watchers = new Array(); //观战者
        this.createTime = new Date().getTime(); //创建房间的时间
        this.record = new Array(); //对局记录
        this.state = RoomState.MATCHING; //房间状态
        this.num_isReadying = 0; //准备就绪人数
        /** 回合结束 */
        this.turnPlayer = null;
        this.id = id;
        this.cipher = cipher;
        console.log("房间创建：id = " + id + ",cipher = " + cipher);
    }
    /** 是否可以加入房间 */
    checkAddPlayer(player) {
        if (this.state == RoomState.MATCHING) {
            return this.checkCreateTimeTooLong() ? true : this.checkSoreRange(player);
        }
        else {
            return false;
        }
    }
    /** 检查房间创建是否过久 */
    checkCreateTimeTooLong() {
        return new Date().getTime() - this.createTime > Config_1.Config.SKIP_GAP_CHECK_TIME;
    }
    /** 检查是否满足分差 */
    checkSoreRange(player) {
        if (this.players.length == 0) {
            return true;
        }
        else if (this.players.length == 1) {
            return Math.abs(this.players[0].score - player.score) < Config_1.Config.SORE_RANGE;
        }
        else {
            return Math.abs(this.players[0].score - player.score) < Config_1.Config.SORE_RANGE && Math.abs(this.players[1].score - player.score) < Config_1.Config.SORE_RANGE;
        }
    }
    /** 检查密码房能否加入玩家 */
    checkCipherRoomAddPlayer(cipher) {
        if (cipher == this.cipher && this.state == RoomState.MATCHING) {
            return true;
        }
        return false;
    }
    /** 添加玩家 */
    addPlayer(player) {
        console.log("添加玩家");
        this.players.push(player);
        player.room = this;
        if (this.players.length == 3) {
            console.log("询问玩家准备好了没");
            this.initReady();
        }
    }
    /** 初始化准备，开一个定时器，防止玩家退出收不到 readyNo */
    initReady() {
        this.num_isReadying = 0;
        this.state = RoomState.READYING;
        this.sendBroadcast({ "isGame": false, "type": "ready" });
        setTimeout(() => {
            if (this.state == RoomState.READYING) {
                this.readyNo();
            }
        }, 5000);
    }
    /** 准备就绪 */
    readyYes() {
        this.num_isReadying++;
        console.log("this.num_isReadying = " + this.num_isReadying);
        //满足3人执行开始游戏
        if (this.num_isReadying == 3) {
            this.startGame();
        }
    }
    /** 拒绝准备 */
    readyNo() {
        this.sendBroadcast({ "isGame": false, "type": "matchingFail" });
        this.closeRoom();
    }
    /** 开始游戏 */
    startGame() {
        console.log("开始游戏");
        this.state = RoomState.GAMEING;
        let obj = { "isGame": false, "type": "start", "data": [this.players[0].username, this.players[1].username, this.players[2].username] };
        this.record.push(obj);
        this.sendBroadcast(obj);
        let obj2 = { "isGame": true, "type": 'turnChange', "data": this.players[0].username };
        this.record.push(obj2);
        this.sendBroadcast(obj2);
        for (let player of this.players) {
            MySQLService_1.default.updateUserRoomId(player.username, this.id);
        }
        //开启回合计时
        this.turnPlayer = this.players[0];
    }
    /** 玩家重连 */
    reconnect(player) {
        for (let i = 0; i < this.players.length; i++) {
            if (player.username == this.players[i].username) {
                this.players[i] = player;
                this.sendBroadcast({ "isGame": false, "type": "reconnect", "data": player.username });
                return;
            }
        }
    }
    /** 房间解散 */
    closeRoom() {
        this.state = RoomState.CLOSE;
        for (let player of this.players) {
            player.is_die = false;
            player.room = null;
            MySQLService_1.default.updateUserRoomId(player.username, 0);
        }
        this.players = null;
        this.watchers = null;
        this.cipher == null ? Mgr_1.default.rooms.delete(this) : Mgr_1.default.cipherRooms.delete(this);
        console.log("房间解散");
    }
    /** 添加观众 */
    addWatcher(watcher) {
        console.log("添加观众");
        this.watchers.push(watcher);
    }
    /** 取消匹配 */
    cancelMatch(player) {
        if (this.state == RoomState.MATCHING) {
            for (let i = 0; i < this.players.length; i++) {
                if (this.players[i] == player) {
                    this.players.splice(i, 1);
                    break;
                }
            }
            if (this.players.length == 0) {
                this.cipher == null ? Mgr_1.default.rooms.delete(this) : Mgr_1.default.cipherRooms.delete(this);
                this.closeRoom();
            }
            player.room = null;
            console.log("取消匹配");
        }
        else {
            console.log("取消匹配失败");
        }
    }
    /** 玩家掉线，检查一下是不是全掉线了 */
    checkPlayersOnLineState() {
        let num_dropLine = 0;
        let winner = null;
        for (let player of this.players) {
            if (!player.is_onLine) {
                num_dropLine++;
            }
            else {
                winner = player;
            }
        }
        if (num_dropLine == 2) {
            //玩家获胜 winner
            this.settleAccounts(winner);
            this.closeRoom();
        }
        else if (num_dropLine == 3) {
            this.closeRoom();
        }
    }
    /** 接收 */
    reciveObj(player, obj) {
        switch (obj.type) {
            case "readyNo":
                this.readyNo();
                break;
            case "readyYes":
                this.readyYes();
                break;
            case "turnOver":
                this.turnOver(player);
                break;
            case "admitDefeat":
                this.admitDefeat(player);
                break;
            case "win":
                this.win(player);
                break;
            case "smallDie":
                this.smallDie(player);
                break;
            default:
                obj.isGame = true;
                this.record.push(obj);
                this.sendBroadcast(obj);
                break;
        }
    }
    /** 房间内广播 */
    sendBroadcast(obj) {
        var _a, _b;
        if (this.state == RoomState.CLOSE) {
            return;
        }
        console.log("服务器发出广播");
        console.log(obj);
        let json = JSON.stringify(obj);
        for (let user of this.players) {
            (_a = user.connection) === null || _a === void 0 ? void 0 : _a.sendText(json);
        }
        for (let user of this.watchers) {
            (_b = user.connection) === null || _b === void 0 ? void 0 : _b.sendText(json);
        }
    }
    /** 分数结算 */
    settleAccounts(winner) {
        console.log("对局结算");
        if (this.state == RoomState.CLOSE) {
            return;
        }
        let scoreChanges = new Array();
        let average_score = Math.floor((this.players[0].score + this.players[1].score + this.players[2].score) / 3);
        for (let player of this.players) {
            let score_gap = Math.abs(average_score - player.score);
            score_gap = score_gap < 10 ? 10 : score_gap;
            let score;
            if (player.score > average_score) { //玩家分数高于其他玩家
                if (player == winner) {
                    score = player.score + 10;
                }
                else {
                    score = player.score - score_gap;
                    score = score < 0 ? 0 : score; //分数不小于0
                }
            }
            else {
                if (player == winner) { //玩家分数低于其他玩家
                    score = player.score + score_gap;
                }
                else {
                    score = player.score - 10;
                    score = score < 0 ? 0 : score; //分数不小于0
                }
            }
            MySQLService_1.default.updateUserScore(player.username, score);
            scoreChanges.push({ "username": player.username, "score": score });
        }
        this.sendBroadcast({ "isGame": true, "type": "gameOver", "data": { "winner": winner.username, "scoreChanges": [scoreChanges[0], scoreChanges[1], scoreChanges[2]] } });
    }
    turnOver(player) {
        console.log("回合结束 " + player.username);
        let nextPlayer = this.players[0];
        for (let i = 0; i < this.players.length; i++) {
            if (player == this.players[i]) {
                if (i < 2) {
                    nextPlayer = this.players[i + 1];
                }
                break;
            }
        }
        //在线 没死 不是当前回合的玩家
        if (nextPlayer.is_onLine && !nextPlayer.is_die && this.turnPlayer != nextPlayer) {
            this.turnPlayer = nextPlayer;
            let obj = { "isGame": true, "type": "turnChange", "data": this.turnPlayer.username };
            this.record.push(obj);
            this.sendBroadcast(obj);
        }
        else {
            this.turnOver(nextPlayer);
        }
    }
    /** 认输 */
    admitDefeat(player) {
        player.is_die = true;
        if (this.turnPlayer == player) {
            this.turnOver(player);
        }
        this.checkPlayersOnLineState();
    }
    /** 玩家获胜 */
    win(player) {
        this.settleAccounts(player);
    }
    /** 玩家死亡 */
    smallDie(player) {
        player.is_die = true;
        if (this.turnPlayer == player) {
            this.turnOver(player);
        }
        let alive_num = 0;
        let winner = null;
        for (let player of this.players) {
            if (player.is_onLine && !player.is_die) {
                alive_num++;
                winner = player;
            }
        }
        if (alive_num == 1) {
            this.settleAccounts(winner);
            this.closeRoom();
        }
    }
}
exports.Room = Room;
var RoomState;
(function (RoomState) {
    RoomState[RoomState["MATCHING"] = 0] = "MATCHING";
    RoomState[RoomState["READYING"] = 1] = "READYING";
    RoomState[RoomState["GAMEING"] = 2] = "GAMEING";
    RoomState[RoomState["CLOSE"] = 3] = "CLOSE"; //已关闭
})(RoomState = exports.RoomState || (exports.RoomState = {}));
